/*
GANESHA - Reasoning on critical infrastructures affected by emergency situations
Copyright (c) 2010-2011, Information Eng. Research Unit - Univ. of Alcala
http://www.cc.uah.es/ie
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package es.uah.cc.ie.ganesha.gis;

import java.io.IOException;
import java.util.Hashtable;
import com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory;
import com.esri.arcgis.geodatabase.IDataset;
import com.esri.arcgis.geodatabase.IEnumDataset;
import com.esri.arcgis.geodatabase.IFeatureClass;
import com.esri.arcgis.geodatabase.IFeatureClassProxy;
import com.esri.arcgis.geodatabase.Workspace;
import com.esri.arcgis.geodatabase.esriDatasetType;
import com.esri.arcgis.system.AoInitialize;
import com.esri.arcgis.system.EngineInitializer;
import com.esri.arcgis.system.esriLicenseProductCode;
import com.esri.arcgis.system.esriLicenseStatus;

/**
 * Class that provides an interface to access to the different GIS layers.
 * @author ieru
 */
public class GISManager {
	private static GISManager _instance = null;

	/**
	 * Singleton
	 * @return Singleton
	 */
	public static GISManager getInstance()
	{
		if(_instance == null)
		{
			_instance = new GISManager();
			_instance.initialize();
		}

		return _instance;
	}

	private boolean _initialized = false;
	private Hashtable<String, GISLayer> _layers = new Hashtable<String, GISLayer>();
	private Hashtable<String, Workspace> _gdbWorkspaces = new Hashtable<String, Workspace>();

	/**
	 * Initializes the ArcGIS system.
	 */
	public void initialize()
	{
		EngineInitializer.initializeEngine();
		initializeArcGISLicenses();

		_initialized = true;
	}

	/**
	 * Returns whether the GIS is initialized or not.
	 * @return true if the GIS is initialized, false if not.
	 */
	public boolean isInitialized()
	{
		return _initialized;
	}

	/**
	 * Returns whether the GIS has information available or not.
	 * @return true if there is information available, false if not.
	 */
	public boolean isAvailable()
	{
		return isInitialized() && !_gdbWorkspaces.isEmpty();
	}

	/**
	 * Returns the layer with the given name if it was already loaded.
	 * @param layerName Name of the layer to be retrieved.
	 * @return The layer or null if there is no layer with the specified name.
	 */
	public GISLayer getLayer(String layerName)
	{
		return _layers.get(layerName);
	}

	/**
	 * Adds a new geographical data source.
	 * @param gdbPath Path to the Geographical DataBase (GDB).
	 * @throws IOException
	 */
	public void addDataSource(String gdbPath) throws IOException
	{
		Workspace workspace = _gdbWorkspaces.get(gdbPath);

		if(workspace == null)
		{
			FileGDBWorkspaceFactory fGDB;

			//Step 1 - Instantiate WorkspaceFactory
			//In this example we are working with a File Geodatabase
			fGDB = new FileGDBWorkspaceFactory();

			//Step 2 - Open the workspace
			//1st argument: ArcCatalog path to the workspace
			//2nd argument: Window Handler - always 0 for us as Java developers
			//Notice that we did NOT cast to Workspace, but created a new instance
			//See Developer Summit presentation for why this is the case
			workspace = new Workspace(fGDB.openFromFile(gdbPath, 0));

			IEnumDataset workspaceLayers = workspace.getDatasets(esriDatasetType.esriDTFeatureClass);
			
			workspaceLayers.reset();
			
			IDataset layer = workspaceLayers.next();
			
			while(layer != null)
			{
				GISLayer newLayer = new GISLayer(new IFeatureClassProxy(layer));

				_layers.put(layer.getName(), newLayer);
				
				layer = workspaceLayers.next();
			}

			_gdbWorkspaces.put(gdbPath, workspace);
		}
	}

	private void initializeArcGISLicenses() {
		try {
			AoInitialize ao = new AoInitialize();

			if (ao.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngine) == esriLicenseStatus.esriLicenseAvailable) {
				ao.initialize(esriLicenseProductCode.esriLicenseProductCodeEngine);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
